﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CheckersLogic;

namespace CheckersUI
{
    public partial class FormUICheckersBoard : Form
    {
        private PictureBoxUICheckersCell[,] m_UIBoard;
        private CheckersMove m_currentMove;
        private string m_moveToInterpretate;
        private GameBoard m_GameBoard;
        private Player m_PlayerX;
        private Player m_PlayerO;
        private Player m_currentPlayer;
        private int m_numberOfPlayers;
        private AnimationHandler m_animationHandler;
        private bool m_UserHasAnotherTurn;

        public FormUICheckersBoard()
        {
            this.m_PlayerX = new Player('X');
            this.m_PlayerO = new Player('O');
            this.m_GameBoard = new GameBoard();
            this.m_UserHasAnotherTurn = false;
            this.m_animationHandler = new AnimationHandler();
            this.m_animationHandler.Visible = false;
            this.Controls.Add(this.m_animationHandler);
            this.InitializeComponent();
        }

        private void UpdateNumberOfPlayers(int i_NumberOfPlayers)
        {
            this.m_numberOfPlayers = i_NumberOfPlayers;
        }

        private void InitializeBoard(int i_GameBoardSize, Player i_PlayerO, Player i_PlayerX)
        {
            this.m_UIBoard = new PictureBoxUICheckersCell[i_GameBoardSize, i_GameBoardSize];
            int k_CellSize = Properties.Resources.CoinRed.Size.Height;

            this.toolStripStatusLabel2.Text = i_PlayerO.Name + " (Red): " + i_PlayerO.Points + ", " + i_PlayerX.Name + " (Yellow): " + i_PlayerX.Points; 

            for (int i = 0; i < i_GameBoardSize; i++)
            {
                for (int j = 0; j < i_GameBoardSize; j++)
                {
                    this.m_UIBoard[i, j] = new PictureBoxUICheckersCell();
                    this.m_UIBoard[i, j].Location = new Point(12 + ((k_CellSize + 5) * i), 30 + ((k_CellSize + 5) * j));
                    this.m_UIBoard[i, j].Size = new Size(Properties.Resources.CoinRed.Size.Width + 5, Properties.Resources.CoinRed.Size.Height + 5);
                    this.m_UIBoard[i, j].Column = (char)(i + 'A');
                    this.m_UIBoard[i, j].Row = (char)(j + 'a');
                    if (i % 2 == j % 2)
                    {
                        this.m_UIBoard[i, j].BackColor = Color.Thistle;
                        this.m_UIBoard[i, j].Enabled = false;
                    }

                    this.m_UIBoard[i, j].OnCellClick += this.WhenButtonClicked;
                    this.m_UIBoard[i, j].OnCellDoubleClick += this.WhenButtonDoubleClicked;
                    this.Controls.Add(this.m_UIBoard[i, j]);
                }
            }

            this.InitialPawnsDrawing(i_PlayerO);
            this.InitialPawnsDrawing(i_PlayerX);
            this.Size = new Size((this.m_GameBoard.Size * (k_CellSize + 5)) + 42, (this.m_GameBoard.Size * (k_CellSize + 3)) + 115); 
        }

        private void InitialPawnsDrawing(Player i_Player)
        {
            Image CoinSymbol;
            List<CheckerCell> playerPawn = i_Player.GetPlayerPawnsArray();
            if(i_Player.Symbol == 'X')
            {
                CoinSymbol = Properties.Resources.CoinYellow;
            }
            else
            {
                CoinSymbol = Properties.Resources.CoinRed;
            }

            foreach (CheckerCell currentCell in playerPawn)
            {
                this.m_UIBoard[currentCell.CellColumn - 'A', currentCell.CellRow - 'a'].Image = CoinSymbol;
                this.m_UIBoard[currentCell.CellColumn - 'A', currentCell.CellRow - 'a'].SizeMode = PictureBoxSizeMode.CenterImage;
                this.m_UIBoard[currentCell.CellColumn - 'A', currentCell.CellRow - 'a'].Symbol = i_Player.Symbol;
            }
        }

        public void WhenButtonClicked(PictureBoxUICheckersCell i_UICheckersCell)
        {
            bool hasTurn = true;
            bool isIllegalMove = false;

            if (i_UICheckersCell.IsClicked)
            {
                if (this.m_moveToInterpretate.Length == 0)
                {
                    if (i_UICheckersCell.Symbol != this.m_currentPlayer.Symbol && i_UICheckersCell.Symbol != ' ' && i_UICheckersCell.Symbol != this.m_currentPlayer.SpecialSymbol)
                    {
                        i_UICheckersCell.BackColor = Color.Orchid;
                        i_UICheckersCell.IsClicked = false;
                        MessageBox.Show("Not your turn");
                    }
                    else if ((i_UICheckersCell.Symbol == this.m_currentPlayer.Symbol || i_UICheckersCell.Symbol == this.m_currentPlayer.SpecialSymbol) && i_UICheckersCell.Symbol != ' ')
                    {
                        this.m_moveToInterpretate += this.TranslateButtonToString(i_UICheckersCell);
                    }
                    else
                    {
                        i_UICheckersCell.BackColor = Color.Orchid;
                        i_UICheckersCell.IsClicked = false;
                    }
                }
                else
                {
                    this.m_moveToInterpretate += ">" + this.TranslateButtonToString(i_UICheckersCell);
                    CheckersGame.CheckForAvailableMoves(ref this.m_currentPlayer, this.m_GameBoard);
                    this.m_currentMove = CheckersGame.InterpretateStringToMove(this.m_moveToInterpretate, this.m_currentPlayer);
                    if (CheckersGame.isInputMoveLegal(this.m_currentMove, this.m_currentPlayer))
                    {
                        hasTurn = CheckersGame.HandlePlayerTurn(this.m_currentPlayer, this.SecondPlayer(), this.m_GameBoard, this.m_currentMove);
                        this.m_UserHasAnotherTurn = hasTurn;
                    }
                    else
                    {
                        this.m_UserHasAnotherTurn = true;
                        isIllegalMove = true;
                        MessageBox.Show("Illegal Move!!");
                    }
                    
                    if (!isIllegalMove && !hasTurn)
                    {
                        CheckersGame.CheckForAvailableMoves(ref this.m_currentPlayer, this.m_GameBoard);
                        this.m_currentPlayer.HasEatingMoves = false;
                        this.m_currentPlayer = this.SecondPlayer();
                    }

                    CheckersGame.CheckForAvailableMoves(ref this.m_currentPlayer, this.m_GameBoard);
                    bool endOfMatch = CheckersGame.IsEndOfMatch(this.m_PlayerO, this.m_PlayerX);
                    if (!endOfMatch)
                    {
                        this.UnClickButtons(this.m_currentMove);
                    }

                    this.m_moveToInterpretate = string.Empty;

                    if (!isIllegalMove && !endOfMatch)
                    {
                        this.ShowAnimation(this.m_currentMove);
                    }
                }
            }
            else
            {
                this.m_moveToInterpretate = string.Empty;
            }
        }

        public void WhenButtonDoubleClicked(PictureBoxUICheckersCell i_UICheckerCell)
        {
            int cellRow;
            int cellColumn;

            this.ConvertCellLocationToInt(i_UICheckerCell, out cellColumn, out cellRow);
            this.m_GameBoard.RemovePawnFromGameboard(cellColumn, cellRow);
            this.m_currentPlayer.RemoveDeletedPawn(new CheckerCell(i_UICheckerCell.Column, i_UICheckerCell.Row, i_UICheckerCell.Symbol));
            this.m_UIBoard[cellColumn, cellRow].Symbol = ' ';
            this.m_UIBoard[cellColumn, cellRow].Image = null;
            this.m_currentPlayer.HasEatingMoves = false;
            CheckersGame.CheckForAvailableMoves(ref this.m_currentPlayer, this.m_GameBoard);
        }

        private void ConvertCellLocationToInt(PictureBoxUICheckersCell i_UICheckersCell, out int i_cellColumn, out int i_cellRow)
        {
            i_cellColumn = (int)(i_UICheckersCell.Column - 'A');
            i_cellRow = (int)(i_UICheckersCell.Row - 'a');
        }

        private void HandleComputerTurn()
        {
            bool hasTurn = true;
            while (hasTurn)
            {
                CheckersGame.CheckForAvailableMoves(ref this.m_currentPlayer, this.m_GameBoard);
                this.m_currentMove = this.m_currentPlayer.GeneratePlayerMove();
                hasTurn = CheckersGame.HandlePlayerTurn(this.m_currentPlayer, this.SecondPlayer(), this.m_GameBoard, this.m_currentMove);
                this.ShowAnimation(this.m_currentMove);
            }

            this.m_currentPlayer = this.SecondPlayer();
        }

        public void HandleEndOfMatch(char i_winningSymbol)
        {
            string output = string.Empty;
            DialogResult usersChoice = new DialogResult();
            switch (i_winningSymbol)
            {
                case 'X':
                    output = this.m_PlayerX.Name + " Won!";
                    CheckersGame.UpdateMatchResult(this.m_PlayerO, this.m_PlayerX, i_winningSymbol);
                    break;
                case 'O':
                    output = this.m_PlayerO.Name + " Won!";
                    CheckersGame.UpdateMatchResult(this.m_PlayerO, this.m_PlayerX, i_winningSymbol);
                    break;
                case 'T':
                    output = "Tie!";
                    break;
                default:
                    break;
            }

            output += System.Environment.NewLine + "Another Round?";
            usersChoice = MessageBox.Show(output, "Damka", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            
            if (usersChoice == System.Windows.Forms.DialogResult.No)
            {
                this.Close();
            }
            else if (usersChoice == System.Windows.Forms.DialogResult.Yes)
            {
                this.UnClickButtons(this.m_currentMove);
                this.startANewGameToolStripMenuItem_Click(new object(), new EventArgs());
            }
        }

        private void UnClickButtons(CheckersMove i_CheckersMove)
        {
            this.m_UIBoard[i_CheckersMove.fromCell.CellColumn - 'A', i_CheckersMove.fromCell.CellRow - 'a'].IsClicked = false;
            this.m_UIBoard[i_CheckersMove.toCell.CellColumn - 'A', i_CheckersMove.toCell.CellRow - 'a'].IsClicked = false;
            this.m_UIBoard[i_CheckersMove.fromCell.CellColumn - 'A', i_CheckersMove.fromCell.CellRow - 'a'].BackColor = Color.Orchid;
            this.m_UIBoard[i_CheckersMove.toCell.CellColumn - 'A', i_CheckersMove.toCell.CellRow - 'a'].BackColor = Color.Orchid;
        }

        public void UpdateUIBoardOnClick(CheckersMove i_moveToUpdate)
        {
            int fromCellRow = (int)(i_moveToUpdate.fromCell.CellRow - 'a');
            int fromCellColumn = (int)(i_moveToUpdate.fromCell.CellColumn - 'A');
            int toCellRow = (int)(i_moveToUpdate.toCell.CellRow - 'a');
            int toCellColumn = (int)(i_moveToUpdate.toCell.CellColumn - 'A');

            this.m_animationHandler.FromCellRowLocation = fromCellRow;
            this.m_animationHandler.FromCellColumnLocation = fromCellColumn;
            this.m_animationHandler.ToCellRowLocation = toCellRow;
            this.m_animationHandler.ToCellColumnLocation = toCellColumn;
            this.m_animationHandler.PlayerSymbol = i_moveToUpdate.MoveSymbol;
            this.updateAnimationDirection(i_moveToUpdate);

            this.m_animationHandler.PawnImage = this.m_UIBoard[fromCellColumn, fromCellRow].Image;
            this.m_UIBoard[fromCellColumn, fromCellRow].Image = null;
            this.m_UIBoard[fromCellColumn, fromCellRow].Symbol = ' ';
        }

        private void updateAnimationDirection(CheckersMove i_moveToUpdate)
        {
            if (i_moveToUpdate.fromCell.CellRow < i_moveToUpdate.toCell.CellRow)
            {
                if (i_moveToUpdate.fromCell.CellColumn < i_moveToUpdate.toCell.CellColumn)
                {
                    this.m_animationHandler.Direction = AnimationHandler.eAnimationDirection.downRight;
                }
                else
                {
                    this.m_animationHandler.Direction = AnimationHandler.eAnimationDirection.downLeft;
                }
            }
            else
            {
                if (i_moveToUpdate.fromCell.CellColumn < i_moveToUpdate.toCell.CellColumn)
                {
                    this.m_animationHandler.Direction = AnimationHandler.eAnimationDirection.upRight;
                }
                else
                {
                    this.m_animationHandler.Direction = AnimationHandler.eAnimationDirection.upLeft;
                }
            }
        }

        private void AtTheEndOfAnimation()
        {
            this.m_UIBoard[this.m_animationHandler.FromCellColumnLocation, this.m_animationHandler.FromCellRowLocation].Symbol = ' ';
            this.m_UIBoard[this.m_animationHandler.ToCellColumnLocation, this.m_animationHandler.ToCellRowLocation].Symbol = this.m_animationHandler.PlayerSymbol;
            this.m_UIBoard[this.m_animationHandler.ToCellColumnLocation, this.m_animationHandler.ToCellRowLocation].Image = this.m_animationHandler.PawnImage;
            this.m_UIBoard[this.m_animationHandler.ToCellColumnLocation, this.m_animationHandler.ToCellRowLocation].BackColor = Color.Orchid;
            this.m_UIBoard[this.m_animationHandler.FromCellColumnLocation, this.m_animationHandler.FromCellRowLocation].BackColor = Color.Orchid;
            this.HandleChangeToSpecialPawn();
            this.HandleEatenPawnDeleteFromBoard();
            this.m_animationHandler.EndOfAnimation = true;
            if (this.m_numberOfPlayers == 1 && this.m_currentPlayer.Symbol != 'O' && !this.m_UserHasAnotherTurn)
            {
                this.HandleComputerTurn();
            }
        }

        private void HandleEatenPawnDeleteFromBoard()
        {
            if (this.m_currentMove.isEatingMove)
            {
                int pawnRowToDelete;
                int pawnColumnToDelete;

                this.m_GameBoard.FindEatenPawnCoordinates(out pawnColumnToDelete, out pawnRowToDelete, this.m_currentMove);
                this.m_UIBoard[pawnColumnToDelete, pawnRowToDelete].Symbol = ' ';
                this.m_UIBoard[pawnColumnToDelete, pawnRowToDelete].Image = null;
            }   
        }

        private void ShowAnimation(CheckersMove i_moveToUpdate)
        {
            int fromCellRow = (int)(i_moveToUpdate.fromCell.CellRow - 'a');
            int fromCellColumn = (int)(i_moveToUpdate.fromCell.CellColumn - 'A');
            int toCellRow = (int)(i_moveToUpdate.toCell.CellRow - 'a');
            int toCellColumn = (int)(i_moveToUpdate.toCell.CellColumn - 'A');

            this.m_animationHandler.Top = this.m_UIBoard[fromCellColumn, fromCellRow].Top;
            this.m_animationHandler.Left = this.m_UIBoard[fromCellColumn, fromCellRow].Left;
            this.m_animationHandler.StopPoint = this.m_UIBoard[toCellColumn, toCellRow].Top;
            this.m_animationHandler.Image = this.m_animationHandler.PawnImage;
            this.m_animationHandler.Visible = true;
            this.m_animationHandler.BackColor = Color.Transparent;

            timerAnimation.Start();
        }

        private void timerAnimation_Tick(object sender, EventArgs e)
        {
            if (this.m_animationHandler.Top == this.m_animationHandler.StopPoint)
            {
                this.m_animationHandler.Visible = false;
                this.timerAnimation.Stop();
                this.AtTheEndOfAnimation();
            }
            else
            {
                int columDirection;
                int rowDirection;
                switch (this.m_animationHandler.Direction)
                {
                    case AnimationHandler.eAnimationDirection.upRight:
                        columDirection = 1;
                        rowDirection = -1;
                        break;
                    case AnimationHandler.eAnimationDirection.upLeft:
                        columDirection = -1;
                        rowDirection = -1;
                        break;
                    case AnimationHandler.eAnimationDirection.downRight:
                        columDirection = 1;
                        rowDirection = 1;
                        break;
                    case AnimationHandler.eAnimationDirection.downLeft:
                        columDirection = -1;
                        rowDirection = 1;
                        break;
                    default:
                        columDirection = 0;
                        rowDirection = 0;
                        break;
                }

                this.m_animationHandler.Top += rowDirection;
                this.m_animationHandler.Left += columDirection;
            }
        }

        private Player SecondPlayer()
        {
            if (this.m_currentPlayer.Symbol == 'X')
            {
                return this.m_PlayerO;
            }
            else
            {
                return this.m_PlayerX;
            }
        }

        private string TranslateButtonToString(PictureBoxUICheckersCell i_UICheckersCell)
        {
            string stringToReturn;
            stringToReturn = i_UICheckersCell.Column.ToString() + i_UICheckersCell.Row.ToString();
            return stringToReturn;
        }

        private void UICheckersBoard_Shown(object sender, EventArgs e)
        {
            GameProperties gameProperties = new GameProperties(ref this.m_GameBoard, ref this.m_PlayerX, ref this.m_PlayerO, ref this.m_numberOfPlayers);
            gameProperties.UpdateNumberOfPlayers += this.UpdateNumberOfPlayers;
            gameProperties.ShowDialog();
            DialogResult dialogResult = new DialogResult();
            dialogResult = gameProperties.DialogResult;
            if (dialogResult == System.Windows.Forms.DialogResult.Cancel)
            {
                this.Close();
            }

            this.InitializeProperties();
        }

        public void HandleChangeToSpecialPawn()
        {
            if (this.m_currentMove.MoveSymbol == 'K')
            {
                if ((int)(this.m_currentMove.toCell.CellRow - 'a') == 0)
                {
                    this.m_UIBoard[this.m_currentMove.toCell.CellColumn - 'A', this.m_currentMove.toCell.CellRow - 'a'].Image = Properties.Resources.CoinYellowKing;
                }
            }
            else
            {
                if ((int)(this.m_currentMove.toCell.CellRow - 'a') == this.m_GameBoard.Size - 1)
                {
                    this.m_UIBoard[this.m_currentMove.toCell.CellColumn - 'A', this.m_currentMove.toCell.CellRow - 'a'].Image = Properties.Resources.CoinRedKing;
                }
            }
        }

        private void InitializeProperties()
        {
            this.m_GameBoard.CreateNewBoard(this.m_GameBoard.Size);
            this.m_PlayerX.InitializePlayerPawnsArray(this.m_GameBoard.Size);
            this.m_PlayerO.InitializePlayerPawnsArray(this.m_GameBoard.Size);
            this.m_currentPlayer = this.m_PlayerO;
            this.m_GameBoard.initializeGameBoardWithPlayersPawns(this.m_PlayerO, this.m_PlayerX);
            this.InitializeBoard(this.m_GameBoard.Size, this.m_PlayerO, this.m_PlayerX);
            this.m_currentMove = new CheckersMove();
            this.m_moveToInterpretate = string.Empty;
            this.m_GameBoard.OnChangeCellStatus += this.UpdateUIBoardOnClick;
            CheckersGame.ThisIsTheEndOfTheMatch += this.HandleEndOfMatch;
            CheckersGame.CheckForAvailableMoves(ref this.m_PlayerO, this.m_GameBoard);
            CheckersGame.CheckForAvailableMoves(ref this.m_PlayerX, this.m_GameBoard);
        }

        private void ClearControlsFromForm()
        {
            for (int i = 0; i < this.m_GameBoard.Size; i++)
            {
                for (int j = 0; j < this.m_GameBoard.Size; j++)
                {
                    this.Controls.Remove(this.m_UIBoard[i, j]);
                }
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void startANewGameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.ClearControlsFromForm();
            this.m_GameBoard.OnChangeCellStatus -= this.UpdateUIBoardOnClick;
            CheckersGame.ThisIsTheEndOfTheMatch -= this.HandleEndOfMatch;
            this.m_PlayerO.HasEatingMoves = false;
            this.m_PlayerX.HasEatingMoves = false;
            this.InitializeProperties();
        }

        private void startANewTournamentToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.m_PlayerO.ClearScoreValue();
            this.m_PlayerX.ClearScoreValue();
            this.startANewGameToolStripMenuItem_Click(sender, e);
        }
    }
}